package com.rex.saas.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.benmanes.caffeine.cache.Cache;
import com.rex.saas.bean.*;
import com.rex.saas.bean.request.AddStrategyTaskRequest;
import com.rex.saas.bean.response.StrategyTaskResponse;
import com.rex.saas.constants.Constants;
import com.rex.saas.db.entity.SaasDeviceInfo;
import com.rex.saas.db.entity.SaasStrategyTask;
import com.rex.saas.enums.StrategyTypeEnum;
import com.rex.saas.service.DeviceService;
import com.rex.saas.service.RexolarApiClient;
import com.rex.saas.service.StrategyTaskService;
import com.rex.saas.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/task")
@Slf4j
public class TaskController extends BaseController{
    @Autowired
    private StrategyTaskService strategyTaskService;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private Cache<String, String> deviceCategoryCache;

    @PostMapping("/trigger")
    @ResponseBody
    public BaseResponse trigger(@RequestBody JSONObject triggerRequest){
//        log.info("trigger:{}", triggerRequest);
        String functionCode = triggerRequest.getString("FunctionCode");
        if("Ack".equals(functionCode)){
            strategyTaskService.ackTaskRecord(triggerRequest);
        }else if("DevReportEvent".equals(functionCode)){
//            String alarmStr = triggerRequest.getString("Alarm");
//            if(!StringUtils.isEmpty(alarmStr)){
//                log.error("alarmStr is null, triggerRequest:{}", triggerRequest);
//                return BaseResponse.error("alarmStr is null", ResultCode.PARAM_ERROR);
//            }
//            JSONObject alarm = JSONObject.parseObject(alarmStr);
//            String codeStr = alarm.getString("Code");
//            if(StringUtils.isEmpty(codeStr)){
//                log.error("codeStr is null, triggerRequest:{}", triggerRequest);
//                return BaseResponse.error("codeStr is null", ResultCode.PARAM_ERROR);
//            }
//            Long time = alarm.getLong("Time");
//            String DeviceId = alarm.getString("DeviceId");
//            return BaseResponse.ok(deviceService.saveDeviceEvent(new DeviceEventData(codeStr, DeviceId, time)));
        }else if("DevReportProperty".equals(functionCode)
                || "DevReportPropertyList".equals(functionCode)
                || "DevWriteResponse".equals(functionCode)
                || "DevWriteResponseList".equals(functionCode)
        ){
            log.info("trigger:{}", triggerRequest);
            String deviceName = triggerRequest.getString("deviceName");
            if(StringUtils.isEmpty(deviceName)){
                log.error("deviceName is null, triggerRequest:{}", triggerRequest);
                return BaseResponse.ok("deviceName is null");
            }
            Map<String, List<PropertyCondition>> triggerTask = strategyTaskService.getTriggerStrategyTasks();
            if(CollectionUtils.isEmpty(triggerTask)){
                log.error("triggerTask is null, triggerRequest:{}", triggerRequest);
                return BaseResponse.ok("triggerTask is null");
            }
            List<PropertyCondition> propertyConditions = triggerTask.get(deviceName);
            if (!CollectionUtils.isEmpty(propertyConditions)){
                for(PropertyCondition propertyCondition : propertyConditions){
                    boolean flag = checkProperty(triggerRequest, propertyCondition);
                    if(flag){
                        boolean executeFlag = strategyTaskService.executeTask(propertyCondition.getTaskId());
                        if(!executeFlag){
                            log.error("executeTaskRecord error, taskId:{}", propertyCondition.getTaskId());
                            return BaseResponse.ok("executeTaskRecord error");
                        }else{
                            log.info("executeTaskRecord success, taskId:{}", propertyCondition.getTaskId());
                            return BaseResponse.ok();
                        }
                    }
                }
            }

            String categoryName = deviceCategoryCache.getIfPresent(deviceName);
            if(!StringUtils.isEmpty(categoryName) && Constants.CT_PROFILE_NAME.equals(categoryName)){
                //

            }
        }else if("NotifyEvent".equals(functionCode)){
            String deviceId = triggerRequest.getString("DeviceId");
            List<SaasDeviceInfo> deviceInfos = deviceService.getByDeviceName(deviceId);
            if(CollectionUtils.isEmpty(deviceInfos)){
                log.error("NotifyEvent getByDeviceName error, deviceId:{}", deviceId);
                return BaseResponse.error(ResultCode.PARAM_ERROR.getStatus(), "deviceId is not exist!");
            }
            SaasDeviceInfo deviceInfo = deviceInfos.get(0);
            if(StringUtils.isEmpty(deviceInfo.getCustomerId())){
                log.error("NotifyEvent deviceInfo.getCustomerId() is null, deviceId:{}", deviceInfo);
                return BaseResponse.error(ResultCode.SYSTEM_ERROR.getStatus(), "设备未绑定！");
            }

            String tenantToken = rexolarApiClient.getTenantToken(deviceInfo.getTenantId());
            if(StringUtils.isEmpty(tenantToken)){
                log.error("NotifyEvent getTenantToken error, tenantId:{}", deviceInfo.getTenantId());
                return BaseResponse.error(ResultCode.SYSTEM_ERROR.getStatus(), "获取租户token失败！");
            }
            if(triggerRequest.get("NetworkLeave")!=null){
                log.info("NotifyEvent NetworkLeave, deviceInfo:{}", deviceInfo);
            }
            if (triggerRequest.get("FactoryReset")!=null){
                boolean flag =  deviceService.reset(deviceInfo.getDeviceName(), tenantToken);
                if (!flag){
                    log.error("NotifyEvent reset error, deviceInfo:{}", deviceInfo);
                    return BaseResponse.error(ResultCode.SYSTEM_ERROR.getStatus(), "设备恢复出厂设置失败！");
                }
            }

        }
        return BaseResponse.ok();
    }

    private String getPropertyValue(String property, JSONObject jsonObject) {
        if(jsonObject.get(property)==null){
            return null;
        }else{
            try{
                JSONObject tmp = jsonObject.getJSONObject(property);
                return tmp.toString();
            }catch (Exception e){
                return jsonObject.getString(property);
            }
        }
    }

    private boolean checkProperty(JSONObject triggerRequest, PropertyCondition propertyCondition) {
        String propertyName = propertyCondition.getPropertyName();
        String propertyValue = null;
        if(propertyName.contains(">")){
            String[] propertys = propertyName.split(">");
            JSONObject jsonObject = triggerRequest;
            for (String property : propertys) {
                if(jsonObject.get(property)==null){
                    break;
                }else{
                    try{
                        jsonObject = jsonObject.getJSONObject(property);
                    }catch (Exception e){
                        propertyValue = jsonObject.getString(property);
                    }
                }
            }
        }else{
            propertyValue = getPropertyValue(propertyName, triggerRequest);
        }

        if(StringUtils.isEmpty(propertyValue)){
           return false;
        }
        switch (propertyCondition.getCompareType()){
            case ">":
                return Double.parseDouble(propertyValue)>Double.parseDouble(propertyCondition.getCompareValue());
            case "<":
                return Double.parseDouble(propertyValue)<Double.parseDouble(propertyCondition.getCompareValue());
            case "==":
                return propertyValue.equals(propertyCondition.getCompareValue());
            case "!=":
                return !propertyValue.equals(propertyCondition.getCompareValue());
            default:
                return false;
        }
    }





}